package order.listeners;

import lombok.RequiredArgsConstructor;
import common.model.order.Orders;
import common.model.result.Result;
import common.model.MulitiDelayMessage;
import order.mq.DelayMessageProcessor;
import order.service.IOrderService;
import common.utils.MqConstants;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;

import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

@Component
@RequiredArgsConstructor
@Slf4j
public class OrderStatusCheckListener {

    @Autowired
    private final IOrderService orderService;

    @Autowired
    private final RabbitTemplate rabbitTemplate;

    @RabbitListener(bindings = @QueueBinding(
        value = @Queue(value = MqConstants.DELAY_QUEUE, durable = "true"),
        exchange = @Exchange(value = MqConstants.DELAY_EXCHANGE, delayed = "true", type = ExchangeTypes.TOPIC),
        key = MqConstants.DELAY_BINDING_KEY
    ))
    public void listenOrederDelayMessage(Message message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) {
        try {
            byte[] messageBody = message.getBody();
            
            try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(messageBody))) {
                MulitiDelayMessage<Long> delayMessage = (MulitiDelayMessage<Long>) ois.readObject();
                Long orderId = delayMessage.getData();
                
                //查询订单状态
                Result orderResult = orderService.getOrderById(orderId);
                
                if (orderResult.getCode() != 200) {
                    // 确认消息已处理
                    channel.basicAck(tag, false);
                    return;
                }
                
                //将orderResult转换为Order对象
                String orderJson = JSON.toJSONString(orderResult.getData());
                
                // 从嵌套结构中获取订单数据
                com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(orderJson);
                Orders order = JSON.parseObject(jsonObject.getString("order"), Orders.class);
                
                //判断订单是否存在
                if (order == null) {
                    // 确认消息已处理
                    channel.basicAck(tag, false);
                    return;
                }
                
                //判断是否已经支付
                if (order.getStatus() != 0) {
                    // 确认消息已处理
                    channel.basicAck(tag, false);
                    return;
                }
                
                //判断是否存在延迟时间
                if (delayMessage.hasDelayTime()) {
                    //存在延迟时间，则重新发送消息
                    Long delayTime = delayMessage.removeDelayTime();
                    rabbitTemplate.convertAndSend(
                        MqConstants.DELAY_EXCHANGE,
                        MqConstants.DELAY_BINDING_KEY,
                        delayMessage,
                        new DelayMessageProcessor(delayTime.intValue())
                    );
                    // 确认消息已处理
                    channel.basicAck(tag, false);
                    return;
                }
                
                //不存在延迟时间，取消订单
                orderService.cancelOrder(order.getId());
                // 确认消息已处理
                channel.basicAck(tag, false);
            }
        } catch (Exception e) {
            log.error("处理延迟消息失败", e);
            try {
                // 消息处理失败，拒绝消息并重新入队
                channel.basicNack(tag, false, true);
            } catch (IOException ex) {
                log.error("消息拒绝失败", ex);
            }
        }
    }
}
